
  @@:
	pop	ecx
	jmp	.hook
  .iat_hook:
	call	@b
	sub	esp, 4*3
	mov	edi, eax
	mov	eax, [ebp+4*2]
	mov	esi, [eax]
	mov	ebx, [eax+4]
	call	.getlen_1
	mov	[ebp-4], eax
	call	.replace1
	mov	ebx, [edi+4*4]
	.if	ebx
	.repeat
		; ebx = FirstThunk
		; edi = Descriptor
		push	edi
		call	.mprot_1
		pop	edi
		add	edi, 4*5
		mov	ebx, [edi+4*4]
	.until	~ebx
	.endif
	leave
	ret

  .iat_hook_lock:
	push	ebx
	mov	ebx, vSyncDllEvent
	invoke	EnterCriticalSection, ebx
	mov	eax, [esp+4*2]
	lea	edx, [esp+4*3]
	call	.iat_hook
	push	eax
	invoke	LeaveCriticalSection, ebx
	pop	eax ebx
	ret

  .getlen_1:
	test	esi, esi
	jnz	@f
  .getlen_null:
	or	eax, -1
	ret
  .getlen_2:
	test	esi, esi
	jz	.getlen_null
	add	esi, [ebp+4*3]
  @@:
	push	esi
	call	[strlen]
	pop	ecx
	.if	eax > 4
		mov	ecx, [esi+eax-4]
		and	ecx, 0xDFDFDFFF
		sub	ecx, '.DLL'
		neg	ecx
		cmc
		sbb	ecx, ecx
		lea	eax, [eax+ecx*4]
	.endif
  @@:
	rep_ret

  .replace1:
	mov	ecx, [ebx]
	btc	ecx, 31
	jz	@b
	mov	[ebx], ecx
	.repeat
		mov	eax, [ebx+4]
		mov	eax, [eax+$-RVA $]
		mov	[ebx+4], eax
		add	ebx, 4*2
	._until ecx
	rep_ret

  .mprot_1:
	mov	esi, [edi+4*3]
	mov	edi, [ebp-4]
	cmp	edi, -1
	je	@f
	call	.getlen_2
	.if	eax = edi
		mov	ecx, [ebp+4*2]
		mov	ecx, [ecx]
		cinvoke memicmp, esi, ecx, eax
		.if	~eax
			call	@f
			leave
		.endif
	.endif
	rep_ret
  @@:
	mov	edi, [ebp+4*3]
	add	edi, ebx
	mov	[ebp-4*2], edi
	xor	eax, eax
	or	ecx, -1
	repnz	scasd
	not	ecx
	mov	ebx, [VirtualProtect]
	lea	esi, [ecx*4]
	lea	edi, [ebp-4*3]
	stdcall ebx, dword [ebp-4*2], esi, PAGE_EXECUTE_READWRITE, edi
	.if	~eax
		stdcall ebx, dword [ebp-4*2], esi, PAGE_READWRITE, edi
		test	eax, eax
		jz	.mprot_1z
	.endif
	mov	ecx, [ebp-4*2]
	push	esi edi dword [edi] esi ecx ebx
	mov	edi, [ebp+4*2]
	.repeat
		mov	ebx, [edi+4]
		mov	esi, [ebx]
		.repeat
			mov	eax, [ebx+4]
			mov	edx, [ebx+4*2]
			nop
			cmpxchg [ecx], edx	; not atomic
			add	ebx, 4*2
		._until esi
		add	ecx, 4
		mov	eax, [ecx]
	.until	~eax
	pop	eax
	call	eax
	pop	eax
  .mprot_1z:
	rep_ret
